/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2014-06-04
 * V4.0
 */
package com.jphenix.kernel.objectloader.util;

import com.jphenix.driver.log.FLog;
import com.jphenix.kernel.baseobject.instanceb.ABase;
import com.jphenix.kernel.objectloader.instanceb.BeanFactory;
import com.jphenix.kernel.objectloader.interfaceclass.IBeanFactory;
import com.jphenix.share.util.SFilesUtil;
import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.standard.log.ILog;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * 搜索指定文件夹中的类
 * 
 * 2018-09-13 简化了整个架构中日志初始化步骤
 * 
 * @author 刘虻
 * 2011-8-19 下午03:12:28
 */
@ClassInfo({"2018-09-13 13:24","搜索指定文件夹中的类"})
public class BeanSearcher extends ABase {
	
	/**
	 * 类根路径只能有一个，因为一个类加载器的根路径只能是一个
	 * 通过扫描类根路径中的类配置文件，加载对应的类
	 * 
	 * 先搜索类文件，然后查找类文件对应的配置文件，既有类文件又有对应的配置文件的类
	 * 为有效类
	 * 
	 * 刘虻
	 * 2010-4-28 上午11:24:18
	 * @throws Exception 执行发生异常
	 */
	public static void search(String classBasePath,IBeanFactory bf) throws Exception {
		ILog log = null; //日志类
		if(bf instanceof BeanFactory) {
			log = FLog.getLog(bf.getLogShadow(),null);
		}
		search(classBasePath,bf,log);
	}
	
	/**
	 * 类根路径只能有一个，因为一个类加载器的根路径只能是一个
	 * 通过扫描类根路径中的类配置文件，加载对应的类
	 * 
	 * 先搜索类文件，然后查找类文件对应的配置文件，既有类文件又有对应的配置文件的类
	 * 为有效类
	 * 
	 * 刘虻
	 * 2010-4-28 上午11:24:18
	 * @throws Exception 执行发生异常
	 */
	public static void search(String searchPath,IBeanFactory bf,ILog log) throws Exception {
		if(searchPath==null || searchPath.length()<1) {
			return;
		}
		//工厂根路径
		String webInfPath = bf.getWebInfPath();
		//判断是不是压缩包中的路径 
		int point = searchPath.indexOf("!");
		if(point>0) {
		    //搜索指定压缩包
		    doSearch(
		            searchPath.substring(point+1)
		            ,SFilesUtil.getAllFilePath(searchPath.substring(0,point),webInfPath)
		            ,bf
		            ,log);
		}else {
		    //搜索指定文件夹
		    doSearch(searchPath,webInfPath,bf,log);
		}
	}
	
	/**
	 * 执行搜索并加载类
	 * @param subPath      搜索相对路径
	 * @param basePath    搜索根路径
	 * @param bf               类加载器
	 * @param log             日志处理类
	 * 2014年4月24日
	 * @author 马宝刚
	 */
	protected static void doSearch(String subPath,String basePath,IBeanFactory bf,ILog log) {
        //记录加载时间
       Object time = null;
       if(log!=null) {
           time = log.runBefore();
       }
       if(basePath!=null && basePath.length()>0) {
    	    //根路径文件对象
    	    File basePathFile = new File(basePath);
    	    if(!basePathFile.exists()) {
    	        log.startLog("Start Scan Bean class Ignore The Path ["+basePath+"] Not Exists");
    	        return;
    	    }
    	    if(basePathFile.isDirectory()) {
    	        subPath = SFilesUtil.getAllFilePath(subPath,basePath);
    	    }else {
    	        if(!subPath.startsWith("/")) {
    	            subPath = "/"+subPath;
    	        }
    	        subPath = basePath+"!"+subPath;
    	    }
       }else {
           subPath = SFilesUtil.getAllFilePath(subPath,null);
       }
       if(log!=null) {
            log.startLog("Start Scan Bean class from ["+subPath+"]...");
       }
       //扫描后新增的类主键序列
       List<String> beanIdList = new ArrayList<String>();
       //文件路径序列
       ArrayList<String> classFilePathArrl = new ArrayList<String>();
       //搜索扩展名
       String extName = "class";
       try {
           SFilesUtil.getFileList(
                   classFilePathArrl
                   ,subPath
                   ,null
                   ,extName
                   ,true
                   ,false);
       }catch(Exception e) {
           e.printStackTrace();
           log.error("Scan Bean class error,ClassBasePath:["+subPath+"]",e);
           return;
       }
       //获取路径下配置文件数量
       int fileCount = classFilePathArrl.size();
       if(log!=null) {
           log.startLog("Total Search class Files ["+fileCount+"] Count");
       }
       String classFilePath = null; //类文件路径
       String xmlFilePath   = null; //对应的配置文件路径
       String beanId        = null; //类主键
       for (int j=0;j<fileCount;j++) {
           //获取一个 Bean 配置文件路径
           classFilePath = classFilePathArrl.get(j);
           //转换为对应的配置文件
           xmlFilePath = classFilePath.substring(0,classFilePath.length()-5)+"xml";
           if(SFilesUtil.isFileExist(xmlFilePath,null)) {
               try {
                   //加载Bean
            	   beanIdList.addAll(bf.addBean(xmlFilePath));
               }catch(Exception e) {
                   e.printStackTrace();
                   log.error("Scan Bean class error:["+xmlFilePath+"]",e);
                   return;
               }
           }else {
               //加载无配置文件类
        	   beanId = bf.addBeanByClassFilePath(classFilePath);
               if(beanId!=null && beanId.length()>0) {
            	   if(!beanIdList.contains(beanId)) {
            		   beanIdList.add(beanId);
            	   }
                   log.startLog("--Load Bean By ClassFilePath:["+classFilePath+"]");
               }
           }
       }
       try {
    	   bf.commitInitBean(beanIdList);
       }catch(Exception e) {
    	   e.printStackTrace();
       }
       if(log!=null) {
           log.writeRuntime(time,"Scan Bean class complete");
       }
	}
}
